﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;

namespace EndGameDBTester
{
    /// <summary>
    /// Central Daphne configuration class - 
    /// - responsible for saving and loading the configuration of various types
    /// </summary>
    public static class Config
    {
        /// <summary>
        /// Configuration hash map
        /// </summary>
        private static Dictionary<string, byte[]> _configHash;

        /// <summary>
        /// Configuration file
        /// </summary>
        private static string _sConfigFile = "EGTBViewer.cfg";

        /// <summary>
        /// Complete configuration file path
        /// </summary>
        private static string _sCompleteFilePath;

        /// <summary>
        /// Init
        /// </summary>
        static Config()
        {
            _configHash = new Dictionary<string, byte[]>();
        }

        /// <summary>
        /// Initializes configuration
        /// </summary>
        public static void InitConfig(string sAppPath)
        {
            _sCompleteFilePath = Path.Combine(sAppPath, _sConfigFile);
            Load();
        }

        /// <summary>
        /// Loads the configuration
        /// </summary>
        private static void Load()
        {
            _configHash.Clear();

            try
            {
                // read the file
                byte[] fileContent = File.ReadAllBytes(_sCompleteFilePath);
                if (fileContent != null)
                {
                    DataTable dTable = Deserialize<DataTable>(fileContent);

                    for (int i = 0; i < dTable.Rows.Count; i++)
                    {
                        DataRow row = dTable.Rows[i];
                        _configHash[row[0] as string] = row[1] as byte[];
                    }                                    
                }
            }
            catch
            {
                // loading config failed, clear the hash
                _configHash.Clear();
            }
        }

        /// <summary>
        /// Saves the configuration
        /// </summary>
        private static void Save()
        {
            try
            {
                // create data table
                DataTable dTable = new DataTable();
                dTable.Columns.Add("Key", typeof(string));
                dTable.Columns.Add("Contnet", typeof(byte[]));

                // save hash map to the datatable
                foreach (var pair in _configHash)
                {
                    dTable.Rows.Add(pair.Key, pair.Value);
                }

                // serialize
                byte[] fileContent = Serialize<DataTable>(dTable);

                // save to the content
                File.WriteAllBytes(_sCompleteFilePath, fileContent);
            }
            catch
            {
            }
        }

        /// <summary>
        /// Gets the settings
        /// </summary>
        public static T Get<T>(string sKey)
        {
            byte[] stream = null;
            if (_configHash.TryGetValue(sKey, out stream) == false)
            {
                return default(T);
            }

            return Deserialize<T>(stream);
        }

        /// <summary>
        /// Sets the settings
        /// </summary>
        public static void Set<T>(string sKey, T value)
        {
            _configHash[sKey] = Serialize<T>(value);
            Save();
        }

        /// <summary>
        /// Deserializes the configuration
        /// </summary>
        private static T Deserialize<T>(byte[] stream)
        {
            try
            {
                MemoryStream memStream = new MemoryStream(stream);
                BinaryFormatter formatter = new BinaryFormatter();
                object objValue = formatter.Deserialize(memStream);
                if (objValue is T)
                {
                    return (T)objValue;
                }
                else
                {
                    return default(T);
                }
            }
            catch
            {
                return default(T);
            }
        }

        /// <summary>
        /// Serializes the configuration
        /// </summary>
        private static byte[] Serialize<T>(T value)
        {
            MemoryStream memStream = new MemoryStream();
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(memStream, value);
            return memStream.ToArray();
        }
    }
}
